package javaDemo.demo.day_04_02_Callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Description Callable 学习
 * @Author
 * @Date 2020/11/1 11:30
 * @Version 1.0
 */
public class CallableDemo {

    /**
     *【 FutureTask 对象使用总结】
     * 1、调用 futureTask.get() 会阻塞 主线程，直到 call 方法执行完，获取到返回值为止；
     * 2、所以一般用 futureTask 创建的线程任务，其结果的获取，最好能往后放就往后放，从而在不影响结果的情况下，保证执行效率；
     * 3、同一个 futureTask 对象，在执行完一次 call 方法得到结果后，相关结果信息就会被缓存在 futureTask 对象内；
     *    即多次让线程去执行 futureTask 中的 call 方法时，call 方法只会调用一次，因为执行完第一次后就能得到结果，下次调用的时候直接将结果返回即可；
     *【 FutureTask 底层源码初识 】
     * 1、FutureTask 类实现了 Runnable 接口，所以 FutureTask 对象，可以放在 new Thread(Runnable runnable,String threadName) 中；
     * 2、并且 FutureTask 类内部，也是实现了 run() 方法的，new Thread(xxx).start() 也是调用其内部的 run() 方法的；
     * 3、FutureTask(Callable callable) 在实例化对象时，可以传递一个 Callable 实例对象；
     * 4、FutureTask 的 run() 方法内部，调用的是 Callable 的 call() 方法；
     * 5、FutureTask 内部封装了许多的缓存、标识属性，可以缓存 run() 执行完 call() 方法后的结果和异常信息；
     * @param args
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        FutureTask futureTask = new FutureTask(new MyThread());

        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start();

        System.out.println("main....");

        System.out.println(futureTask.get());

    }
}

/**
 *【Callable 和 Runnable 的不同点】
 * 1、run() --> call()
 * 2、线程方法 可以抛异常
 * 3、线程方法 有返回值
 * 4、Callable 线程的调用方式改变
 */
class MyThread implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println("Callable... come in here ...");
        return 1024;
    }
}
